﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Web.Routing;

using ProjectBase.Core;
using ProjectBase.Core.Web;

namespace $safeprojectname$
{
    public class AsyncComboBox : DetailLinkControl<IPersistentObject, AsyncComboBox>
    {
        #region members
        #endregion members

        #region constructor
        public AsyncComboBox() { }
        public AsyncComboBox(bool? asReadonly = null) : base(asReadonly) { }
        public AsyncComboBox(string prefix) : base(prefix) { }
        #endregion constructor

        #region OnSourceProperty
        protected override void OnSourcePropertyChanged(string propertyName, IPersistentObject value)
        {
            base.OnSourcePropertyChanged(propertyName, value);

            SetAsyncController(Type.Name);

            if (value.Is())
            {
                SetDetailEntityID(value.IDToDisplay);
                SetComboBoxSelectedValue(value.IDToDisplay);
                SetText(value.ToDisplay());
            }
        }
        #endregion OnSourceProperty

        #region Render
        protected override void ReadControls()
        {
            Controls.Add(CreateDivControls());
        }

        protected override void WriteControls()
        {
            HideLinkToDetail(true);
            Controls.Add(CreateAsyncControls());
        }

        protected virtual Div CreateDivControls()
        {
            return new Div(GetAttribute(Attr.Class))
            {
                new Span
                {
                    new Anchor()
                        .SetTitle(Text.Length > MaxLength ? Text : null)
                        .SetTitle(Title)
                        .SetHref(HasDetailLink ? DetailUrl : null)
                        .SetCssClassName(HasDetailLink ? null : "none noPointer")
                        .AddControls
                        (
                            new Literal(Text.ToLength(MaxLength, true))
                        )
                }
            };
        }

        protected virtual Div CreateAsyncControls()
        {
            return CreateDivControls()
                .AddControls
                (
                    new Button(Special.Ellipsis)
                        .SetCssClassName("async")
                        .SetName("asyncComboBox")
                        .SetAttribute("data-asyncurl", AsyncUrl),

                    // in case, that ComboBox is not async loaded, pass Hidden field
                    ComboBoxSelectedValue.IsEmpty() // if any selected value exists
                    ? null
                    : new Input(InputType.Hidden)
                        .SetName(InputName)
                        .SetValue(DetailEntityID)
                );
        }
        #endregion Render

        #region public Set()
        /// <summary>
        ///     Dynamically sets the property AsyncController
        /// </summary>
        /// <param name = "controller">not null nor empty controller name</param>
        /// <returns>this</returns>
        public virtual AsyncComboBox SetAsyncController(string controller)
        {
            if (controller.IsNotEmpty())
            {
                AsyncController = controller;
            }
            return this;
        }

        /// <summary>
        ///     Dynamically sets the property AsyncAction
        /// </summary>
        /// <param name = "action">not null nor empty action name</param>
        /// <returns>this</returns>
        public virtual AsyncComboBox SetAsyncAction(string action)
        {
            if (action.IsNotEmpty())
            {
                AsyncAction = action;
            }
            return this;
        }

        /// <summary>
        ///     Dynamically sets the selected value to be used in ComboBox
        /// </summary>
        /// <param name = "selectedValue">not null</param>
        /// <returns>this</returns>
        public virtual AsyncComboBox SetComboBoxSelectedValue(object selectedValue)
        {
            if (selectedValue.Is())
            {
                var persistent = selectedValue as IPersistentObject;
                if (persistent.Is())
                {
                    ComboBoxSelectedValue = persistent.IDToDisplay;
                    SetText(persistent.ToDisplay());
                }
                else
                {
                    ComboBoxSelectedValue = selectedValue.ToString();
                    SetText(ComboBoxSelectedValue);
                }
            }
            return this;
        }

        /// <summary>
        ///     Dynamically sets the property CombBoxName.
        ///     If not set, AsyncController is used.
        /// </summary>
        /// <param name = "comboBoxName">not null nor empty</param>
        /// <returns>this</returns>
        public virtual AsyncComboBox SetComboBoxName(string comboBoxName)
        {
            if (comboBoxName.IsNotEmpty())
            {
                ComboBoxName = comboBoxName;
            }
            return this;
        }

        /// <summary>
        ///     Dynamically sets the property CombBoxShowEmpty
        /// </summary>
        /// <param name = "comboBoxShowEmpty"></param>
        /// <returns>this</returns>
        public virtual AsyncComboBox SetComboBoxShowEmpty(bool comboBoxShowEmpty)
        {
            ComboBoxShowEmpty = comboBoxShowEmpty;
            return this;
        }
        #endregion public Set()

        #region protected Create RouteValues
        /// <summary>
        ///     Collects all properties needed for async combobox action handling.
        ///     Sets the Combo's Name, Css, HasEmptyOption settings
        ///     and extends them with others stored in TargetQueryStringParams collection
        /// </summary>
        /// <returns></returns>
        protected override RouteValueDictionary CreateRouteValues()
        {
            var rvd = base.CreateRouteValues();
            rvd[Constants.WebControls.Ajax.ParamCurrentComboName] = ComboBoxName ?? InputName;
            rvd[Constants.WebControls.Ajax.ParamCssClassName] = ComboBoxCssClassName ?? string.Empty;
            rvd[Constants.WebControls.Ajax.ParamShowEmpty] = ComboBoxShowEmpty;
            rvd[Constants.WebControls.Ajax.ParamSelectedID] = ComboBoxSelectedValue;
            return rvd;
        }
        #endregion protected Create RouteValues

        #region properties
        /// <summary>
        ///     Default value is "ComboBox".
        ///     The Action, which renders the async ComboBox
        /// </summary>
        public virtual string AsyncAction { get; set; }

        /// <summary>
        ///     Controller providing 'AsyncAction' (e.g. "ComboBox")
        /// </summary>
        public virtual string AsyncController { get; set; }

        public virtual string ComboBoxCssClassName { get; set; }
        public virtual bool ComboBoxShowEmpty { get; set; }
        public virtual string ComboBoxName { get; set; }
        public virtual string ComboBoxSelectedValue { get; set; }

        /// <summary>
        ///     Creates the correct url for async action
        ///     using needed AsyncComboBox's properties
        /// </summary>
        /// <returns></returns>
        protected virtual string AsyncUrl
        {
            get
            {
                if (AsyncController.IsEmpty()
                    && DetailController.IsEmpty())
                {
                    return null;
                }
                return Url.Action(
                    AsyncAction ?? Constants.WebControls.Ajax.ActionGetComboBox,
                    AsyncController.IsNotEmpty() ? AsyncController : DetailController,
                    CreateRouteValues());
            }
        }
        public override string InputName
        {
            get { return base.InputName + ".ID"; }
            set { base.InputName = value; }
        }
        #endregion properties
    }
}